"use client";
import {
  useState,
  useEffect,
  useContext,
  useCallback,
  memo,
  useRef,
} from "react";
import { Box, Flex, Button, useToast } from "@chakra-ui/react";
import { DPIGroup, DpiConfig } from "@/src/types/types.d";
import { MouseConfigInfo } from "@/src/types/types";
import { MainContext } from "@/src/providers/MainProvider";
import { RepeatIcon } from "@chakra-ui/icons";
import { useTranslation } from "@/src/i18n";
import DpiInputGroup from "./DPISetting/DpiInputGroup";
import DpiSliderSection from "./DPISetting/DpiSliderSection";
import defaultDataConfig from "@/src/config/mouse_info_v1000.json";
import { hexToGrb } from "@/src/utils/colorUtils";
import MouseInfoToast from "../Common/MouseInfoToast";

const DEFAULT_DPI_GROUPS: DPIGroup[] = defaultDataConfig.dpi;
const DPI_CONFIG: DpiConfig = defaultDataConfig.dpiConfig;

const DpiSetting = () => {
  const {
    connectedMouse,
    currentTab,
    mouseConfigInfo,
    setMouseConfigInfo,
    mouseDpi,
    mouseReportRate,
    profile,
    profileIndex,
    mouseDPIInfo,
    mouseDPIGroups,
    dpiSyncData,
    setDpiSyncData,
    // 添加DPI协议相关状态
    dpiColors,
    dpiProtocolControl,
    updateDpiColors,
  } = useContext(MainContext);

  const [dpiGroups, setDpiGroups] = useState<DPIGroup[]>(DEFAULT_DPI_GROUPS);
  const [dpiConfig, setDpiConfig] = useState<DpiConfig>(DPI_CONFIG);
  const [selectedDpi, setSelectedDPI] = useState(DPI_CONFIG.defaultSelected);
  const [curDpiValue, setCurDpiValue] = useState(
    DEFAULT_DPI_GROUPS[DPI_CONFIG.defaultSelected].dpiValue
  );
  const [curDpiEditValue, setCurDpiEditValue] = useState(
    DEFAULT_DPI_GROUPS[DPI_CONFIG.defaultSelected].dpiValue
  );
  const [dpiCount, setDpiCount] = useState(DPI_CONFIG.defaultCount);
  const { t } = useTranslation("");
  const toast = useToast();

  // 防抖定时器引用与延时常量
  const radioChangeDebounceRef = useRef<number | null>(null);
  const RADIO_CHANGE_DEBOUNCE_MS = 300;
  // 记录最近一次由本组件主动触发 toast 的时间，避免与驱动回报产生的重复弹窗
  const lastUiToastTimestampRef = useRef<number>(0);
  // 记录上一次从驱动层观察到的 dpi 档位与值
  const prevDriverDpiIndexRef = useRef<number | null>(null);
  const prevDriverDpiValueRef = useRef<number | null>(null);
  // 初始化延迟标志和定时器引用
  const [isInitialized, setIsInitialized] = useState<boolean>(false);
  const initDelayTimerRef = useRef<number | null>(null);

  const showMouseInfoToast = (
    dpiLevel: number,
    dpiValue: number,
    reportRate: number
  ) => {
    toast({
      title: t("mouseInfoUpdated"),
      status: "success",
      duration: 3000,
      position: "bottom-right",
      isClosable: true,
      render: ({ onClose }) => (
        <MouseInfoToast
          data={{
            dpiLevel,
            dpiValue,
            reportRate,
          }}
          onClose={onClose}
        />
      ),
    });
  };

  const updateMouseConfigData = useCallback(
    (updatedConfig: MouseConfigInfo) => {
      if (connectedMouse) {
        setMouseConfigInfo(updatedConfig);
        if (profile) {
          profile.updateMouseConfig(profileIndex, updatedConfig);
        } else {
          console.warn("profile is null, updateMouseConfig skipped.");
        }
        connectedMouse.setMouseConfigData(updatedConfig);
      } else {
        console.warn("connectedMouse is null, updateMouseConfigData skipped.");
      }
    },
    [connectedMouse, profile, profileIndex, setMouseConfigInfo]
  );

  const updateMouseConfig = useCallback(
    (configInfo: MouseConfigInfo | null) => {
      if (!configInfo) return;
      const newDpiIndex = Math.max(configInfo.dpi_index, 0);
      const newDpiCount = Math.max(configInfo.dpi_count, 1);
      const validDpiIndex = Math.min(newDpiIndex, newDpiCount - 1);
      setSelectedDPI(validDpiIndex);
      setDpiCount(newDpiCount);
      const newDpiGroups = dpiGroups.map((group, index) => ({
        ...group,
        dpiValue:
          configInfo[`dpi${index + 1}_value` as keyof typeof configInfo] ||
          group.dpiValue,
      }));
      setDpiGroups(newDpiGroups);
      setCurDpiValue(newDpiGroups[validDpiIndex]?.dpiValue ?? 800);
      setCurDpiEditValue(newDpiGroups[validDpiIndex]?.dpiValue ?? 800);
    },
    [dpiGroups]
  );

  const handleRadioBoxChange = (value: string) => {
    const newSelectDpi = parseInt(value);
    setSelectedDPI(newSelectDpi);
    const newDpiValue = dpiGroups[newSelectDpi]?.dpiValue ?? 800;
    setCurDpiValue(newDpiValue);
    setCurDpiEditValue(newDpiValue);

    if (mouseConfigInfo) {
      updateMouseConfigData({
        ...mouseConfigInfo,
        dpi_index: newSelectDpi,
      });

      showMouseInfoToast(
        newSelectDpi,
        newDpiValue,
        mouseConfigInfo.report_rate === 0
          ? 125
          : mouseConfigInfo.report_rate === 1
          ? 250
          : mouseConfigInfo.report_rate === 2
          ? 500
          : 1000
      );
      lastUiToastTimestampRef.current = Date.now();
    }
  };

  const handleDpiInputValueChanging = (value: number, index: number) => {
    if (index == selectedDpi) {
      setCurDpiEditValue(value);
    }
  };

  const handleDpiValueChanging = (value: number) => {
    // 确保值不小于最小值
    const validValue = Math.max(value, dpiConfig.min);
    setCurDpiValue(validValue);
    setCurDpiEditValue(validValue);
  };

  // DPI值最终变化（当输入完成时更新）
  const handleDpiValueChange = useCallback(
    (value: number) => {
      if (isNaN(value)) {
        value = dpiConfig.min;
      }

      value = Math.max(dpiConfig.min, Math.min(value, dpiConfig.max));

      setCurDpiValue(value);
      setCurDpiEditValue(value);

      setDpiGroups((prevGroups) => {
        // 更新当前选中DPI的值
        const updatedGroups = prevGroups.map((group, index) => ({
          ...group,
          dpiValue: index === selectedDpi ? value : group.dpiValue,
        }));

        // 获取排序后的DPI值数组
        const sortedDpiValues = updatedGroups.map((group) => group.dpiValue);
        // .sort((a, b) => a - b);  // 去除 dpi 自动排序

        const newUpdatedGroups = updatedGroups.map((group, index) => ({
          ...group,
          dpiValue: sortedDpiValues[index],
        }));

        const newSelectedIndex = newUpdatedGroups.findIndex(
          (group) => group.dpiValue === value
        );
        setSelectedDPI(newSelectedIndex);

        // 更新配置
        if (mouseConfigInfo) {
          // 将配置更新与 toast 触发做防抖，避免短时间多次触发
          if (radioChangeDebounceRef.current) {
            window.clearTimeout(radioChangeDebounceRef.current);
          }

          radioChangeDebounceRef.current = window.setTimeout(() => {
            const updatedConfig = {
              ...mouseConfigInfo,
              dpi_index: newSelectedIndex,
            };

            newUpdatedGroups.forEach((group, index) => {
              updatedConfig[
                `dpi${index + 1}_value` as keyof typeof updatedConfig
              ] = group.dpiValue;
            });
            updateMouseConfigData(updatedConfig);
          }, RADIO_CHANGE_DEBOUNCE_MS);
        }

        return newUpdatedGroups;
      });
    },
    [
      mouseConfigInfo,
      selectedDpi,
      dpiConfig.min,
      dpiConfig.max,
      updateMouseConfigData,
    ]
  );

  const handleResetDPISettings = useCallback(async () => {
    if (mouseDPIGroups && mouseDPIGroups.length > 2) {
      setDpiGroups(mouseDPIGroups);
      setDpiCount(dpiConfig.defaultCount);
      setSelectedDPI(dpiConfig.defaultSelected);
      setCurDpiValue(mouseDPIGroups[dpiConfig.defaultSelected].dpiValue);
      setCurDpiEditValue(mouseDPIGroups[dpiConfig.defaultSelected].dpiValue);
    } else {
      console.warn("mouseDPIGroups is empty or does not have enough entries");
    }

    if (mouseConfigInfo) {
      const {
        dpi1_value,
        dpi2_value,
        dpi3_value,
        dpi4_value,
        dpi5_value,
        dpi6_value,
      } = defaultDataConfig.DefaultProfile.defaultConfig;

      await updateMouseConfigData({
        ...mouseConfigInfo,
        dpi_index: dpiConfig.defaultSelected,
        dpi_count: dpiConfig.defaultCount,
        dpi1_value,
        dpi2_value,
        dpi3_value,
        dpi4_value,
        dpi5_value,
        dpi6_value,
      });
      await dpiProtocolControl.configureDpiColors();

      if (mouseDPIGroups && mouseDPIGroups.length > 0) {
        setDpiGroups(mouseDPIGroups);
      }
    } else {
      console.warn("mouseConfigInfo is null, updateMouseConfigData skipped.");
    }
  }, [mouseConfigInfo, mouseDPIGroups, dpiConfig, updateMouseConfigData]);

  const handleEditDpiData = async (
    value: number,
    color: string,
    index: number
  ) => {
    const newColors = { ...dpiColors };
    console.log("newColors", newColors);
    const currentColorArray = [...newColors.colors[0]];

    currentColorArray[index] = hexToGrb(color);
    newColors.colors[0] = currentColorArray;

    await updateDpiColors(newColors);

    setDpiGroups((prevGroups) => {
      const updatedGroups = [...prevGroups];
      updatedGroups[index] = {
        ...updatedGroups[index],
        dpiColor: color,
        dpiBgColor: `${color}1a`,
      };
      return updatedGroups;
    });

    await handleDpiValueChange(value);
  };

  useEffect(() => {
    // 组件挂载时启动3秒延迟定时器
    initDelayTimerRef.current = window.setTimeout(() => {
      setIsInitialized(true);
    }, 3000);

    // 组件卸载时清理定时器
    return () => {
      if (radioChangeDebounceRef.current) {
        window.clearTimeout(radioChangeDebounceRef.current);
      }
      if (initDelayTimerRef.current) {
        window.clearTimeout(initDelayTimerRef.current);
      }
    };
  }, []);

  useEffect(() => {
    if (mouseConfigInfo && dpiSyncData) {
      updateMouseConfig(mouseConfigInfo);
      setDpiSyncData(false);
    }
  }, [mouseConfigInfo, dpiSyncData, updateMouseConfig, setDpiSyncData]);

  useEffect(() => {
    if (dpiGroups.length > 0) {
      setSelectedDPI(mouseDpi);
      const newDpiValue = dpiGroups[mouseDpi]?.dpiValue ?? 800;
      setCurDpiValue(newDpiValue);
      setCurDpiEditValue(newDpiValue);
    }
  }, [mouseDpi]);

  useEffect(() => {
    if (!dpiGroups || dpiGroups.length === 0) return;

    // 只有在初始化完成后才监听 mouseDpi 变化
    if (!isInitialized) return;

    const currentIndex = mouseDpi;
    const currentValue = dpiGroups[currentIndex]?.dpiValue ?? 800;

    const prevIndex = prevDriverDpiIndexRef.current;
    const prevValue = prevDriverDpiValueRef.current;

    const indexChanged = prevIndex !== null && prevIndex !== currentIndex;
    const valueChanged = prevValue !== null && prevValue !== currentValue;

    // 初次初始化不弹窗，仅在后续变化时弹窗
    if (prevIndex !== null || prevValue !== null) {
      if (indexChanged || valueChanged) {
        const now = Date.now();

        if (now - lastUiToastTimestampRef.current > 500) {
          const reportRateCode =
            mouseConfigInfo?.report_rate ?? mouseReportRate ?? 0;
          const reportRateHz =
            reportRateCode === 0
              ? 125
              : reportRateCode === 1
              ? 250
              : reportRateCode === 2
              ? 500
              : 1000;
          showMouseInfoToast(currentIndex, currentValue, reportRateHz);
        }
      }
    }

    prevDriverDpiIndexRef.current = currentIndex;
    prevDriverDpiValueRef.current = currentValue;
  }, [
    mouseDpi,
    dpiGroups,
    mouseConfigInfo?.report_rate,
    mouseReportRate,
    isInitialized,
  ]);

  // 初始化DPI配置
  useEffect(() => {
    if (mouseDPIInfo) {
      setDpiGroups(mouseDPIGroups);
      setDpiConfig(mouseDPIInfo);
    }
  }, [mouseDPIInfo, mouseDPIGroups]);

  useEffect(() => {
    if (currentTab !== "mousedpi") {
      setDpiSyncData(true);
    } else {
      updateMouseConfig(mouseConfigInfo);

      setTimeout(() => {
        connectedMouse.getMouseConfigInfo().then((res) => {
          setMouseConfigInfo(res);
          setSelectedDPI(res.dpi_index);

          const currentDpiValue = dpiGroups[res.dpi_index]?.dpiValue ?? 800;

          setCurDpiValue(currentDpiValue);
          setCurDpiEditValue(currentDpiValue);
        });
      }, 150);
    }
  }, [currentTab]);

  useEffect(() => {
    setDpiSyncData(true);
  }, [profileIndex]);

  return (
    <Box className="flex flex-col h-full justify-between gap-8 ">
      <Flex justifyContent="space-between" alignItems="center" p={1}>
        <Flex></Flex>
        <Button
          onClick={handleResetDPISettings}
          minWidth="160px"
          height="36px"
          variant="outline"
          fontWeight="normal"
          ml="auto"
          leftIcon={<RepeatIcon />}
        >
          {t("restDefaultSetting")}
        </Button>
      </Flex>

      <Flex justifyContent="center" alignItems="center" p={4}>
        <DpiInputGroup
          dpiGroups={dpiGroups}
          selectedDpi={selectedDpi}
          curDpiEditValue={curDpiEditValue}
          dpiConfig={dpiConfig}
          onRadioChange={handleRadioBoxChange}
          onInputValueChanging={handleDpiInputValueChanging}
          onEditDpiData={handleEditDpiData}
        />
      </Flex>

      <DpiSliderSection
        curDpiValue={curDpiValue}
        selectedDpi={selectedDpi}
        dpiGroups={dpiGroups}
        dpiConfig={dpiConfig}
        onDpiValueChanging={handleDpiValueChanging}
        onDpiValueChange={handleDpiValueChange}
      />
    </Box>
  );
};

export default memo(DpiSetting);
